package com.yu.learn.aop;

import java.lang.reflect.Method;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.collect.Lists;
import com.yu.learn.annotation.WxMonitorNotice;
import com.yu.learn.service.WxNoticeService;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信企业通知AOP
 * @author yushijun
 * @date 2018/5/9
 */
@Aspect
@Component
@Slf4j
public class WxMonitorNoticeAspect {

    @Autowired
    WxNoticeService wxNoticeService;

    @AfterThrowing(throwing = "exception",value = "pointCut()")
    public void afterThrowAspect(JoinPoint joinPoint,Throwable exception) {

        try {

            // 获取目标类
//            Class targetClass = Class.forName(targetClassName);
//            String methodName = joinPoint.getSignature().getName();
//            Object[] arguments = joinPoint.getArgs();
//            Method[] methods = targetClass.getMethods();
            // 获取切面类
            Class targetClass = joinPoint.getTarget().getClass();
            // 获取切面方法Signature
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            Method currentMethod = methodSignature.getMethod();
            log.info("微信通知AOP处理开始class:{},method:{}",targetClass.getName(),currentMethod.getName());

            // 获取当前AOP切面方法
            Method targetClassMethod = Lists.newArrayList(targetClass.getMethods()).stream()
                    .filter(method -> method.equals(currentMethod)).findFirst().get();
            // 获取 WxMonitorNotice 注解信息
            WxMonitorNotice notice = targetClassMethod.getAnnotation(WxMonitorNotice.class);
            String topic = notice.topic();
//            Class serviceException = notice.exception();
            // 需要统一ServiceException 否则无法识别--TODO 优化使用注解定义Exception 的方式，Exception 需要集成RunTimeException，获取message
//            if(exception instanceof ServiceException){
//                ServiceException serviceException = (ServiceException)exception;
//                wxNoticeService.wxNoticeSend(topic + serviceException.getMessage());
//            }

            //判断两个Class 是否一致，一致获取exception中的message做为微信content的信息;(和@Transaction中的rollbackfor 不同，不存在继承关系)
            Class serviceException = notice.exception();
            if(!serviceException.equals(exception.getClass())){
                log.info("微信通知AOP不做处理class:{},method:{},className:{}",targetClass.getName(),currentMethod.getName(),exception.getClass().getName());
                return;
            }
            wxNoticeService.wxNoticeSend(topic + exception.getMessage());
            log.info("微信通知AOP处理结束class:{},method:{},exception:{}",targetClass.getName(),currentMethod.getName(),exception.getMessage());
        }catch (Exception e){
            log.error("微信通知处理-异常Exception",e);
        }

    }

    @Pointcut("@annotation(com.yu.learn.annotation.WxMonitorNotice)")
    public void pointCut() {
    }

}
